home *** CD-ROM | disk | FTP | other *** search
-
- These are some patches for the V1.1 and V1.12 gopherd so it can talk to
- FTP servers that do not understand the PASV command.
-
- It also can tell directories from files from file-listings issued by some
- VMS FTP servers.
-
- This has been tested with:
- - one VMS FTP server running Wollongong-FTP V 5.1,
- - one VMS FTP server running Multinet-FTP V 3.1.
- - one Ultrix-RISC FTP server running 4.2 and one with 4.1,
- - boombox.micro.umn.edu, which seems to be a Mac running some
- version of A/UX.
-
- Apparently, Multinet 3.2 does understand the PASV command, but this will
- not help, since the format of directory listings is still not what the
- original gopherd expects.
-
-
- To apply this patch:
-
- Gopher 1.12: cd to the gopher1.12 directory and say: patch -p < thisfile
- Gopher 1.1 : cd to the gopher1.1 directory and say: patch -p -F3 < thisfile
-
- (You will get some "with fuzz n" and "offset n lines" messages with gopher1.1,
- ignore these).
-
- Patched files are: object/GSgopherobj.c gopherd/ftp.c gopherd/gopherd.c
-
- Then rebuild gopherlib.a and gopherd:
-
- % rm object/gopherlib.a
- % make server
-
-
- To use the extensions for VMS FTP servers, you must say:
-
- Path=ftp-vms:vms.ftp.server@/
-
- and for Ultrix or A/UX FTP servers ("nop" stands for "no-PASV"):
-
- Path=ftp-nop:ultrix.ftp.serv@/
-
- where you would usually write
-
- Path=ftp:unix.ftp.server@/
-
- in a .Links file.
-
- +-----------
- Andi Karrer, Communication Systems, ETH Zuerich, Switzerland
- karrer@bernina.ethz.ch - Objects in mirror are closer than they appear
- +-----------
-
- *** object/GSgopherobj.c.dist Mon Jan 11 20:54:22 1993
- --- object/GSgopherobj.c Sun Feb 21 23:11:49 1993
- ***************
- *** 1,3 ****
- --- 1,10 ----
- + /*
- + * Added support for VMS FTP servers that do not understand the FTP PASV
- + * command (Wollongong, Multinet). Also present these servers output
- + * in a Unix fashion.
- + * Also works with Ultrix 4.2 FTP servers whose PASV command is broken.
- + * Andi Karrer, karrer@bernina.ethz.ch, 21. Feb 93
- + */
- /********************************************************************
- * $Author: lindner $
- * $Revision: 1.1.1.3 $
- ***************
- *** 408,413 ****
- --- 415,499 ----
- closenet(iSock);
- return (-4);
- }
- + return(iSock);
- + }
- +
- + /* needed for FTP servers without PASV */
- + #include <errno.h>
- +
- + /* GSlisten opens a port and listens to it */
- +
- + int
- + GSlisten(We)
- + struct sockaddr_in * We;
- + {
- + int iSock = 0;
- + struct hostent *HostPtr;
- + int len = sizeof(struct sockaddr_in);
- + char name[100];
- +
- + if ((iSock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- + return (-3);
- +
- + /* Cargo cult; no idea if these options are good here */
- +
- + #ifndef UCX
- + setsockopt(iSock, SOL_SOCKET, ~SO_LINGER, 0, 0);
- + #endif
- + setsockopt(iSock, SOL_SOCKET, SO_REUSEADDR, 0, 0);
- + setsockopt(iSock, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
- +
- + if (listen(iSock, 5) || getsockname(iSock, We, &len)) {
- + closenet(iSock);
- + return(-4);
- + }
- +
- + gethostname(name, 100);
- + if (HostPtr = gethostbyname(name))
- + bcopy(HostPtr->h_addr, (char *) &We->sin_addr, HostPtr->h_length);
- + return(iSock);
- + }
- +
- + /* GSaccept accepts a connection from some socket. The parameter
- + * full_hostname will, on return,
- + * contain the expanded hostname (if possible). Note that full_hostname is a
- + * pointer to a char *, and is allocated by connect_to_gopher()
- + *
- + * Errors:
- + *
- + * -1 get service failed
- + *
- + * -2 get host failed
- + *
- + * -3 socket call failed
- + *
- + * -4 connect call failed
- + */
- +
- + int
- + GSaccept(s, gs)
- + int s;
- + GopherObj *gs;
- + {
- + struct sockaddr_in Server;
- + struct hostent *HostPtr;
- + int ERRinet = -1;
- + int iSock = 0;
- + int len = sizeof(struct sockaddr_in);
- +
- + #ifdef _CRAY
- + ERRinet = 0xFFFFFFFF; /* -1 doesn't sign extend on 64 bit machines */
- + #endif
- +
- + if ((iSock = accept(s, &Server, &len)) < 0) {
- + printf("Aaaargh! %d", errno);
- + return -4;
- + }
- +
- + GSsetPort(gs, ntohs(Server.sin_port));
- +
- + close(s); /* Der Mohr hat seine Schuldigkeit getan */
- +
- return(iSock);
- }
-
- *** gopherd/ftp.c.dist Tue Jan 12 00:16:39 1993
- --- gopherd/ftp.c Sun Feb 21 23:12:01 1993
- ***************
- *** 1,3 ****
- --- 1,10 ----
- + /*
- + * Added support for VMS FTP servers that do not understand the FTP PASV
- + * command (Wollongong, Multinet). Also present these servers output
- + * in a Unix fashion.
- + * Also works with Ultrix 4.2 FTP servers whose PASV command is broken.
- + * Andi Karrer, karrer@bernina.ethz.ch, 21. Feb 93
- + */
- /********************************************************************
- * $Author: lindner $
- * $Revision: 1.2 $
- ***************
- *** 62,67 ****
- --- 69,76 ----
- int gettingBinary = 0;
- int childpid;
-
- + extern int no_pasv, is_vms;
- +
- /*** Some forward declarations ***/
- boolean NotText();
- int Abort();
- ***************
- *** 323,329 ****
- while (fgets(buf, sizeof buf, fp) != NULL) {
- ZapCRLF(buf);
- GopherType(buf, theName);
- ! sprintf(outputline, "%s\tftp:%s@%s%s\t%s\t%d\r\n", theName,
- host, thing, buf, Zehostname, GopherPort);
- FailErr(writestring(sockfd, outputline));
- }
- --- 332,339 ----
- while (fgets(buf, sizeof buf, fp) != NULL) {
- ZapCRLF(buf);
- GopherType(buf, theName);
- ! sprintf(outputline, "%s\t%s:%s@%s%s\t%s\t%d\r\n", theName,
- ! no_pasv ? is_vms ? "ftp-vms" : "ftp-nop" : "ftp",
- host, thing, buf, Zehostname, GopherPort);
- FailErr(writestring(sockfd, outputline));
- }
- ***************
- *** 430,438 ****
- int extType, i, last;
- char tmpName[SLEN];
-
- ! last = strlen(buf) -1;
- !
- strcpy(tmpName, buf);
- if (buf[last] == '/') {
- tmpName[last] = '\0';
- sprintf(theName, "%d%s", GDIR, tmpName);
- --- 440,468 ----
- int extType, i, last;
- char tmpName[SLEN];
-
- ! last = strlen(buf) - 1;
- ! while (buf[last] == ' ') {
- ! buf[last] = '\0';
- ! last--;
- ! }
- ! if (is_vms) {
- ! /* strip ugly VMS version numbers */
- ! last = strlen(buf) - 1;
- ! while(last>1 && isdigit(buf[last])) last--;
- ! if (last>1 && buf[last] == ';') {
- ! buf[last] = '\0';
- ! last--;
- ! }
- ! }
- strcpy(tmpName, buf);
- + /* if buf ends in ".dir", it's a directory, replace ".dir" with "/" */
- + if (is_vms && (last > 3) && (strncmp(buf + last - 3, ".dir", 4) == 0)) {
- + last -= 3;
- + tmpName[last] = '\0';
- + sprintf(buf, "%s/", tmpName);
- + sprintf(theName, "%d%s", GDIR, tmpName);
- + return;
- + }
- if (buf[last] == '/') {
- tmpName[last] = '\0';
- sprintf(theName, "%d%s", GDIR, tmpName);
- ***************
- *** 521,523 ****
- --- 551,758 ----
- }
-
- /*--------------------------------*/
- +
- + void
- + SendNoPASVFtpQuery(sockfd, query)
- + char *query;
- + {
- + int sLen, termCh, i;
- + char *at, *cp;
- + char inputline[512];
- + char buf[1600]; /*** Nice MTU size ***/
- + int tmpfd;
- + int ftp_control, ftp_data;
- + int ftp_dataport, nRead;
- + GopherObj *gs;
- + struct sockaddr_in we;
- + char vmspath[256], vmsfile[80];
- + char *beg, *end;
- + int len;
- + int makelower;
- +
- + /*** hook onto the gs code to do our ftp socket connects ***/
- + gs = GSnew();
- +
- + /** Get ready for some cleanup action **/
- + signal(SIGPIPE, Cleanup);
- + signal(SIGINT, Cleanup);
- + signal(SIGALRM, Cleanup);
- +
- + if (DEBUG) printf("The full query was %s\n", query);
- +
- + if ((sLen = strlen(query)) <= 2) Abort(sockfd,"No host name specified.");
- + host = query;
- + at = strchr(query, '@');
- +
- + if (at == NULL) Abort(sockfd, "Not a valid ftp query.");
- +
- + GenerateUniqueFiles(ftptmp);
- + tmpfd = uopen(ftptmp, O_RDWR|O_CREAT,0755);
- +
- + if (tmpfd < 0)
- + Abort(sockfd, "Sorry, out of tmp transfer space!");
- +
- + thing = at + 1;
- + *at = '\0'; /*Sneakily chop it into two strings*/
- +
- + sLen = strlen(thing);
- + termCh = thing[sLen - 1]; /* Grab possible end char: / etc */
- +
- + if ((termCh == '*') || (termCh == '@')) /* || (termCh == '/') */
- + thing[sLen - 1] = '\0';
- +
- + if (DEBUG)
- + printf("At this point host: %s thing: %s\n", host, thing);
- +
- +
- + /*** Open an ftp control connection ***/
- + GSsetHost(gs, host);
- + GSsetPort(gs, 21);
- +
- + ftp_control = GSconnect(gs);
- + if (ftp_control < 0)
- + Abort(sockfd, "unable to connect to ftp server!");
- +
- + /*** Strip off the connection message ***/
- + getreply(ftp_control,inputline,sizeof inputline);
- +
- + if (*inputline != '2')
- + /*** Some sort of error, urg! ***/
- + Abort(sockfd, inputline +3);
- +
- + /*** Send username ***/
- + writestring(ftp_control, "USER anonymous\r\n");
- + if (DEBUG) printf("Send: USER anonymous CRLF\n");
- +
- + getreply(ftp_control,inputline,sizeof inputline);
- +
- + if (*inputline != '3')
- + /*** Some sort of error, urg! ***/
- + Abort(sockfd, inputline +3);
- +
- + /** Send password***/
- + writestring(ftp_control, "PASS -gopher@");
- + writestring(ftp_control, Zehostname);
- + writestring(ftp_control, "\r\n");
- + if (DEBUG) printf("Send: PASS -gopher@%s\n", Zehostname);
- +
- + getreply(ftp_control,inputline,sizeof inputline);
- +
- + if (*inputline != '2')
- + /*** Some sort of error, urg! ***/
- + Abort(sockfd, inputline +3);
- +
- + if ((ftp_dataport = GSlisten(&we)) < 0)
- + Abort(sockfd, "no clue what socket error!");
- +
- + sprintf(inputline, "PORT %d,%d,%d,%d,%d,%d\r\n",
- + (htonl(we.sin_addr.s_addr) >> 24) & 0xFF,
- + (htonl(we.sin_addr.s_addr) >> 16) & 0xFF,
- + (htonl(we.sin_addr.s_addr) >> 8) & 0xFF,
- + (htonl(we.sin_addr.s_addr) ) & 0xFF,
- + (htons(we.sin_port) >> 8) & 0xFF,
- + (htons(we.sin_port) ) & 0xFF);
- + if (DEBUG) printf("Send: %s", inputline);
- +
- + writestring(ftp_control, inputline);
- +
- + getreply(ftp_control,inputline,sizeof inputline);
- +
- + if (*inputline != '2')
- + /*** Some sort of error, urg! ***/
- + Abort(sockfd, inputline +3);
- +
- + if (termCh == '/') { /* We have a directory */
- + if (DEBUG) printf("(It's a directory)\n");
- + gettingFile = 0;
- + /* thing looks like '/dir/dir.../dir/' now. Because Wollongong
- + * wants "CWD dir/dir/dir" and Multinet wants "CWD dir.dir.dir"
- + * we do the CWD in a stepwise fashion. Oh well...
- + */
- + beg = thing + 1;
- + while (beg < thing + strlen(thing) - 2) {
- + end = strchr(beg, '/');
- + strcpy(vmspath, beg);
- + vmspath[end-beg] = '\0';
- + writestring(ftp_control, "CWD ");
- + writestring(ftp_control, vmspath);
- + writestring(ftp_control, "\r\n");
- + if (DEBUG) printf("Send: CWD %s CRLF\n", vmspath);
- + getreply(ftp_control,inputline,sizeof inputline);
- + if (*inputline != '2')
- + Abort(sockfd,inputline + 4);
- + beg = end + 1;
- + }
- + if (DEBUG) printf("Send: %s\n", is_vms ? "NLST" : "NLST -LF");
- + writestring(ftp_control, is_vms ? "NLST\r\n" : "NLST -LF\r\n");
- + getreply(ftp_control,inputline,sizeof inputline);
- + makelower = 1;
- +
- + if (*inputline != '1')
- + Abort(sockfd,inputline + 4);
- + }
- + else { /* We have a file */
- + if (DEBUG) printf("(It's a file)\n");
- + gettingFile = 1;
- + if (gettingBinary = IsBinaryType(thing)) {
- + writestring(ftp_control, "TYPE I\r\n");
- + if (DEBUG) printf("Send: TYPE I\n");
- + getreply(ftp_control,inputline,sizeof inputline);
- + if (*inputline != '2')
- + Abort(sockfd,"Unable to transfer files in binary");
- + }
- + /* thing now looks like '/dir/dir/file.ext' */
- + strcpy(vmspath, thing);
- + len = strlen(vmspath) - 1;
- + while (len > 1 && vmspath[len] != '/') len--;
- + beg = vmspath + 1;
- + while ((end = strchr(beg, '/')) != NULL) {
- + strcpy(vmsfile, beg);
- + vmsfile[end-beg] = '\0';
- + writestring(ftp_control, "CWD ");
- + writestring(ftp_control, vmsfile);
- + writestring(ftp_control, "\r\n");
- + if (DEBUG) printf("Send: CWD %s CRLF\n", vmsfile);
- + getreply(ftp_control,inputline,sizeof inputline);
- + if (*inputline != '2')
- + Abort(sockfd,inputline + 4);
- + beg = end + 1;
- + }
- + beg = strrchr(thing, '/') + 1;
- + writestring(ftp_control, "RETR ");
- + writestring(ftp_control, beg);
- + writestring(ftp_control, "\r\n");
- + if (DEBUG) printf("Send: RETR %s CRLF\n", beg);
- + makelower = 0;
- +
- + getreply(ftp_control,inputline,sizeof inputline);
- + if (*inputline != '1')
- + Abort(sockfd,inputline + 4);
- + }
- + ftp_data = GSaccept(ftp_dataport, gs);
- + if (ftp_data < 0)
- + Abort(sockfd,"Unable to establish data connection!");
- + /*** Transfer the data... ***/
- + while ((nRead = read(ftp_data, buf, sizeof buf)) > 0) {
- + if (makelower && is_vms) {
- + for (i=0; i<nRead; i++) buf[i] = tolower(buf[i]);
- + }
- + writen(tmpfd, buf, nRead);
- + }
- +
- + close(ftp_data);
- +
- + getreply(ftp_control,inputline,sizeof inputline);
- +
- + if (*inputline != '2')
- + Abort(sockfd,inputline + 3);
- +
- + writestring(ftp_control, "QUIT\r\n");
- +
- + getreply(ftp_control,inputline,sizeof inputline);
- +
- + if (*inputline != '2')
- + Abort(sockfd,inputline + 3);
- +
- + close(ftp_control);
- + }
- *** gopherd/gopherd.c.dist Mon Jan 11 20:07:42 1993
- --- gopherd/gopherd.c Sun Feb 21 23:12:13 1993
- ***************
- *** 1,3 ****
- --- 1,10 ----
- + /*
- + * Added support for VMS FTP servers that do not understand the FTP PASV
- + * command (Wollongong, Multinet). Also present these servers output
- + * in a Unix fashion.
- + * Also works with Ultrix 4.2 FTP servers whose PASV command is broken.
- + * Andi Karrer, karrer@bernina.ethz.ch, 21. Feb 93
- + */
- /********************************************************************
- * $Author: lindner $
- * $Revision: 1.2.1.6 $
- ***************
- *** 56,61 ****
- --- 63,70 ----
- void LOGGopher();
-
- static int uid = -2;
- + int no_pasv = 0;
- + int is_vms = 0;
-
- extern char *getdesc();
- extern double maxload;
- ***************
- *** 655,660 ****
- --- 664,670 ----
- do_command(sockfd)
- int sockfd;
- {
- + extern int no_pasv;
- char inputline[MAXLINE];
- int length; /* Length of the command line */
- char logline[MAXLINE];
- ***************
- *** 916,921 ****
- --- 926,932 ----
- }
-
- if (strncmp(selstr, "ftp:",4)==0){
- + no_pasv = 0;
- sprintf(logline, "retrieved %s", selstr);
- LOGGopher(sockfd, logline);
-
- ***************
- *** 923,928 ****
- --- 934,949 ----
- TranslateResults(sockfd);
- break;
- }
- + is_vms = (strncmp(selstr, "ftp-vms:",8) == 0);
- + if ((is_vms) || (strncmp(selstr, "ftp-nop:",8) == 0)) {
- + no_pasv = 1;
- + sprintf(logline, "retrieved %s", selstr);
- + LOGGopher(sockfd, logline);
- +
- + SendNoPASVFtpQuery(sockfd, selstr+8);
- + TranslateResults(sockfd);
- + break;
- + }
- break;
-
- case 'e':
-